/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.assertj.ohos.api.components;

import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentParent;
import ohos.agp.components.element.Element;
import ohos.global.resource.NotExistException;
import ohos.global.resource.WrongTypeException;
import org.assertj.core.api.AbstractAssert;

import java.io.IOException;

import static ohos.agp.components.Component.LayoutDirection;
import static ohos.agp.components.Component.VISIBLE;
import static ohos.agp.components.Component.INVISIBLE;
import static ohos.agp.components.Component.HIDE;
import static ohos.agp.components.Component.AXIS_X;
import static ohos.agp.components.Component.AXIS_Y;

import static org.assertj.ohos.internal.BitmaskUtils.buildNamedValueString;
import static org.assertj.core.api.Assertions.assertThat;

/** 组件断言 */
public abstract class ComponentAssert<S extends ComponentAssert<S, A>, A extends Component>
    extends AbstractAssert<S, A> {
    protected ComponentAssert(A actual, Class<S> selfType) {
    super(actual, selfType);
    }

    /**
    * 透明度
    *
    * @param alpha 透明度
    * @return S
    */
    public S hasAlpha(float alpha) {
    isNotNull();
    float actualAlpha = actual.getAlpha();
    assertThat(actualAlpha) //
        .overridingErrorMessage("Expected alpha <%s> but was <%s>", alpha, actualAlpha) //
        .isEqualTo(alpha);
    return myself;
    }

    /**
    * 动画
    *
    * @param animation 属性动画
    * @return S
    */
    public S hasAnimation(AnimatorProperty animation) {
    isNotNull();
    AnimatorProperty actualAnimation = actual.createAnimatorProperty();
    assertThat(actualAnimation) //
        .overridingErrorMessage("Expected animation <%s> but was <%s>", animation,
            actualAnimation) //
        .isSameAs(animation);
    return myself;
    }

    /**
    * 背景
    *
    * @param background 背景
    * @return S
    */
    public S hasBackground(Element background) {
    isNotNull();
    Element actualDrawable = actual.getBackgroundElement();
    assertThat(actualDrawable) //
        .overridingErrorMessage("Expected background <%s> but was <%s>", background,
            actualDrawable) //
        .isSameAs(background);
    return myself;
    }

    /**
    * 底部
    *
    * @param bottom 底部
    * @return S
    */
    public S hasBottom(int bottom) {
    isNotNull();
    int actualBottom = actual.getBottom();
    assertThat(actualBottom) //
        .overridingErrorMessage("Expected bottom <%s> but was <%s>", bottom, actualBottom) //
        .isEqualTo(bottom);
    return myself;
    }

    /**
    * 内容描述
    *
    * @param contentDescription 内容描述
    * @return S
    */
    public S hasContentDescription(CharSequence contentDescription) {
    isNotNull();
    CharSequence actualContentDescription = actual.getComponentDescription();
    assertThat(actualContentDescription) //
        .overridingErrorMessage("Expected content description <%s> but was <%s>",
            contentDescription, actualContentDescription) //
        .isEqualTo(contentDescription);
    return myself;
    }

    /**
    * 内容描述
    *
    * @param resId 资源id
    * @return S
    * @throws NotExistException 不存在异常
    * @throws WrongTypeException 错误类型异常
    * @throws IOException IO异常
    */
    public S hasContentDescription(int resId) throws NotExistException, WrongTypeException, IOException {
    isNotNull();
    String tmp = actual.getContext().getResourceManager().getElement(resId).getString();
    return hasContentDescription(tmp);
    }

    /**
    * 高
    *
    * @param height 高
    * @return S
    */
    public S hasHeight(int height) {
    isNotNull();
    int actualHeight = actual.getHeight();
    assertThat(actualHeight) //
        .overridingErrorMessage("Expected height <%s> but was <%s>", height, actualHeight) //
        .isEqualTo(height);
    return myself;
    }

    /**
    * 有水平衰落边缘长度
    *
    * @param length 长度
    * @return S
    */
    public S hasHorizontalFadingEdgeLength(int length) {
    isNotNull();
    int actualLength = actual.getFadeEffectBoundaryWidth();
    assertThat(actualLength) //
        .overridingErrorMessage("Expected horizontal fading edge length <%s> but was <%s>", length,
            actualLength) //
        .isEqualTo(length);
    return myself;
    }

    /**
    * id
    *
    * @param id id
    * @return S
    */
    public S hasId(int id) {
    isNotNull();
    int actualId = actual.getId();
    assertThat(actualId) //
        .overridingErrorMessage("Expected ID <%s> but was <%s>", Integer.toHexString(id),
            Integer.toHexString(actualId)) //
        .isEqualTo(id);
    return myself;
    }

    /**
    * 布局方向
    *
    * @param direction 布局方向
    * @return S
    */
    public S hasLayoutDirection(LayoutDirection direction) {
    isNotNull();
    LayoutDirection actualDirection = actual.getLayoutDirection();
    assertThat(actualDirection) //
        .overridingErrorMessage("Expected layout direction <%s> but was <%s>",
            layoutDirectionToString(direction), layoutDirectionToString(actualDirection)) //
        .isEqualTo(direction);
    return myself;
    }

    /**
    * 左
    *
    * @param left 左
    * @return S
    */
    public S hasLeft(int left) {
    isNotNull();
    int actualLeft = actual.getLeft();
    assertThat(actualLeft) //
        .overridingErrorMessage("Expected left <%s> but was <%s>", left, actualLeft) //
        .isEqualTo(left);
    return myself;
    }

    /**
    * 测量高度
    *
    * @param height 高
    * @return S
    */
    public S hasMeasuredHeight(int height) {
    isNotNull();
    int actualHeight = actual.getHeight();
    assertThat(actualHeight) //
        .overridingErrorMessage("Expected measured height <%s> but was <%s>", height,
            actualHeight) //
        .isEqualTo(height);
    return myself;
    }

    /**
    * 测量宽度
    *
    * @param width 宽
    * @return S
    */
    public S hasMeasuredWidth(int width) {
    isNotNull();
    int actualWidth = actual.getWidth();
    assertThat(actualWidth) //
        .overridingErrorMessage("Expected measured width <%s> but was <%s>", width, actualWidth) //
        .isEqualTo(width);
    return myself;
    }

    /**
    * 最小高度
    *
    * @param height 高
    * @return S
    */
    public S hasMinimumHeight(int height) {
    isNotNull();
    int actualHeight = actual.getMinHeight();
    assertThat(actualHeight) //
        .overridingErrorMessage("Expected minimum height <%s> but was <%s>", height,
            actualHeight) //
        .isEqualTo(height);
    return myself;
    }

    /**
    * 最小宽度
    *
    * @param width 宽
    * @return S
    */
    public S hasMinimumWidth(int width) {
    isNotNull();
    int actualWidth = actual.getMinWidth();
    assertThat(actualWidth) //
        .overridingErrorMessage("Expected minimum width <%s> but was <%s>", width, actualWidth) //
        .isEqualTo(width);
    return myself;
    }

    /**
    * 向下内间距
    *
    * @param padding 内间距
    * @return S
    */
    public S hasPaddingBottom(int padding) {
    isNotNull();
    int actualPadding = actual.getPaddingBottom();
    assertThat(actualPadding) //
        .overridingErrorMessage("Expected padding bottom <%s> but was <%s>", padding,
            actualPadding) //
        .isEqualTo(padding);
    return myself;
    }

    /**
    * 向右内间距
    *
    * @param padding 内间距
    * @return S
    */
    public S hasPaddingEnd(int padding) {
    isNotNull();
    int actualPadding = actual.getPaddingEnd();
    assertThat(actualPadding) //
        .overridingErrorMessage("Expected padding end <%s> but was <%s>", padding, actualPadding) //
        .isEqualTo(padding);
    return myself;
    }

    /**
    * 向左内间距
    *
    * @param padding 内间距
    * @return S
    */
    public S hasPaddingLeft(int padding) {
    isNotNull();
    int actualPadding = actual.getPaddingLeft();
    assertThat(actualPadding) //
        .overridingErrorMessage("Expected padding left <%s> but was <%s>", padding,
            actualPadding) //
        .isEqualTo(padding);
    return myself;
    }

    /**
    * 向右内间距
    *
    * @param padding 内间距
    * @return S
    */
    public S hasPaddingRight(int padding) {
    isNotNull();
    int actualPadding = actual.getPaddingRight();
    assertThat(actualPadding) //
        .overridingErrorMessage("Expected padding right <%s> but was <%s>", padding,
            actualPadding) //
        .isEqualTo(padding);
    return myself;
    }

    /**
    * 向左内间距
    *
    * @param padding 内间距
    * @return S
    */
    public S hasPaddingStart(int padding) {
    isNotNull();
    int actualPadding = actual.getPaddingStart();
    assertThat(actualPadding) //
        .overridingErrorMessage("Expected padding start <%s> but was <%s>", padding,
            actualPadding) //
        .isEqualTo(padding);
    return myself;
    }

    /**
    * 向上内间剧
    *
    * @param padding 内间距
    * @return S
    */
    public S hasPaddingTop(int padding) {
    isNotNull();
    int actualPadding = actual.getPaddingTop();
    assertThat(actualPadding) //
        .overridingErrorMessage("Expected padding top <%s> but was <%s>", padding, actualPadding) //
        .isEqualTo(padding);
    return myself;
    }

    /**
     * 具有父组件
     *
     * @param parent 父组件
     * @return S
     */
    public S hasParent(ComponentParent parent) {
    isNotNull();
    ComponentParent actualParent = actual.getComponentParent();
    assertThat(actualParent) //
        .overridingErrorMessage("Expected parent <%s> but was <%s>", parent, actualParent) //
        .isSameAs(parent);
    return myself;
    }

    /**
    * 有父类辅助功能
    *
    * @param parent 父组件
    * @return S
    */
    public S hasParentForAccessibility(ComponentParent parent) {
    isNotNull();
    ComponentParent actualParent = actual.getComponentParent();
    assertThat(actualParent) //
        .overridingErrorMessage("Expected parent for accessibility <%s> but was <%s>", parent,
            actualParent) //
        .isSameAs(parent);
    return myself;
    }

    /**
    * x轴旋转值
    *
    * @param pivotX x轴旋转值
    * @return S
    */
    public S hasPivotX(float pivotX) {
    isNotNull();
    float actualPivotX = actual.getPivotX();
    assertThat(actualPivotX) //
        .overridingErrorMessage("Expected x pivot <%s> but was <%s>", pivotX, actualPivotX) //
        .isEqualTo(pivotX);
    return myself;
    }

    /**
    * y轴旋转值
    *
    * @param pivotY y轴旋转值
    * @return S
    */
    public S hasPivotY(float pivotY) {
    isNotNull();
    float actualPivotY = actual.getPivotY();
    assertThat(actualPivotY) //
        .overridingErrorMessage("Expected y pivot <s> but was <%s>", pivotY, actualPivotY) //
        .isEqualTo(pivotY);
    return myself;
    }

    /**
    * 右
    *
    * @param right 右
    * @return S
    */
    public S hasRight(int right) {
    isNotNull();
    int actualRight = actual.getRight();
    assertThat(actualRight) //
        .overridingErrorMessage("Expected right <%s> but was <%s>", right, actualRight) //
        .isEqualTo(right);
    return myself;
    }

    /**
    * 旋转值
    *
    * @param rotation 旋转值
    * @return S
    */
    public S hasRotation(float rotation) {
    isNotNull();
    float actualRotation = actual.getRotation();
    assertThat(actualRotation) //
        .overridingErrorMessage("Expected rotation <%s> but was <%s>", rotation, actualRotation) //
        .isEqualTo(rotation);
    return myself;
    }

    /**
    * x轴拉伸值
    *
    * @param scale 拉伸值
    * @return S
    */
    public S hasScaleX(float scale) {
    isNotNull();
    float actualScale = actual.getScaleX();
    assertThat(actualScale) //
        .overridingErrorMessage("Expected x scale <%s> but was <%s>", scale, actualScale) //
        .isEqualTo(scale);
    return myself;
    }

    /**
    * y轴拉伸值
    *
    * @param scale 拉伸值
    * @return S
    */
    public S hasScaleY(float scale) {
    isNotNull();
    float actualScale = actual.getScaleY();
    assertThat(actualScale) //
        .overridingErrorMessage("Expected y scale <%s> but was <%s>", scale, actualScale) //
        .isEqualTo(scale);
    return myself;
    }

    /**
    * X轴滚动值
    *
    * @param scroll 滚动值
    * @return S
    */
    public S hasScrollX(int scroll) {
    isNotNull();
    int actualScroll = actual.getScrollValue(Component.AXIS_X);
    assertThat(actualScroll) //
        .overridingErrorMessage("Expected x scroll <%s> but was <%s>", scroll, actualScroll) //
        .isEqualTo(scroll);
    return myself;
    }

    /**
    * y轴滚动值
    *
    * @param scroll 滚动值
    * @return S
    */
    public S hasScrollY(int scroll) {
    isNotNull();
    int actualScroll = actual.getScrollValue(Component.AXIS_Y);
    assertThat(actualScroll) //
        .overridingErrorMessage("Expected y scroll <%s> but was <%s>", scroll, actualScroll) //
        .isEqualTo(scroll);
    return myself;
    }

    /**
    * 标签
    *
    * @param tag 标签
    * @return S
    */
    public S hasTag(Object tag) {
    isNotNull();
    Object actualTag = actual.getTag();
    assertThat(actualTag) //
        .overridingErrorMessage("Expected tag <%s> but was <%s>", tag, actualTag) //
        .isEqualTo(tag);
    return myself;
    }

    /**
    * 上
    *
    * @param top 上
    * @return S
    */
    public S hasTop(int top) {
    isNotNull();
    int actualTop = actual.getTop();
    assertThat(actualTop) //
        .overridingErrorMessage("Expected top <%s> but was <%s>", top, actualTop) //
        .isEqualTo(top);
    return myself;
    }

    /**
    * x轴位移值
    *
    * @param translation 位移值
    * @return S
    */
    public S hasTranslationX(float translation) {
    isNotNull();
    float actualTranslation = actual.getTranslationX();
    assertThat(actualTranslation) //
        .overridingErrorMessage("Expected x translation <%s> but was <%s>", translation,
            actualTranslation) //
        .isEqualTo(translation);
    return myself;
    }

    /**
    * Y轴位移值
    *
    * @param translation 位移值
    * @return S
    */
    public S hasTranslationY(float translation) {
    isNotNull();
    float actualTranslation = actual.getTranslationY();
    assertThat(actualTranslation) //
        .overridingErrorMessage("Expected y translation <%s> but was <%s>", translation,
            actualTranslation) //
        .isEqualTo(translation);
    return myself;
    }

    /**
    * 垂直衰落边缘长度
    *
    * @param length 长度
    * @return S
    */
    public S hasVerticalFadingEdgeLength(int length) {
    isNotNull();
    int actualLength = actual.getFadeEffectBoundaryWidth();
    assertThat(actualLength) //
        .overridingErrorMessage("Expected vertical fading edge length <%s> but was <%s>", length,
            actualLength) //
        .isEqualTo(length);
    return myself;
    }

    /**
    * 显示
    *
    * @param visibility 显示
    * @return S
    */
    public S hasVisibility(int visibility) {
    isNotNull();
    int actualVisibility = actual.getVisibility();
    assertThat(actualVisibility) //
        .overridingErrorMessage("Expected visibility <%s> but was <%s>.",
            visibilityToString(visibility), visibilityToString(actualVisibility)) //
        .isEqualTo(visibility);
    return myself;
    }

    /**
    * 是否可见
    *
    * @return S
    */
    public S isVisible() {
    isNotNull();
    int actualVisibility = actual.getVisibility();
    // noinspection ResourceType
    assertThat(actualVisibility) //
        .overridingErrorMessage("Expected to be visible but was %s",
            visibilityToString(actualVisibility)) //
        .isEqualTo(VISIBLE);
    return myself;
    }

    /**
    * 是否不可见
    *
    * @return S
    */
    public S isNotVisible() {
    isNotNull();
    int actualVisibility = actual.getVisibility();
    assertThat(actualVisibility) //
        .overridingErrorMessage("Expected to be not visible but was visible") //
        .isNotEqualTo(VISIBLE);
    return myself;
    }

    /**
    * 是否可见（占据位置，但不可见）
    *
    * @return S
    */
    public S isInvisible() {
    isNotNull();
    int actualVisibility = actual.getVisibility();
    assertThat(actualVisibility) //
        .overridingErrorMessage("Expected to be invisible but was %s",
            visibilityToString(actualVisibility)) //
        .isEqualTo(INVISIBLE);
    return myself;
    }

    /**
    * 是否不可见（占据位置，但不可见）
    *
    * @return S
    */
    public S isNotInvisible() {
    isNotNull();
    int actualVisibility = actual.getVisibility();
    assertThat(actualVisibility) //
        .overridingErrorMessage("Expected to be not invisible but was invisible") //
        .isNotEqualTo(INVISIBLE);
    return myself;
    }

    /**
    * 是否隐藏
    *
    * @return S
    */
    public S isGone() {
    isNotNull();
    int actualVisibility = actual.getVisibility();
    assertThat(actualVisibility) //
        .overridingErrorMessage("Expected to be gone but was %s",
            visibilityToString(actualVisibility)) //
        .isEqualTo(HIDE);
    return myself;
    }

    /**
    * 是否显示
    *
    * @return S
    */
    public S isNotGone() {
    isNotNull();
    int actualVisibility = actual.getVisibility();
    assertThat(actualVisibility) //
        .overridingErrorMessage("Expected to be not gone but was gone") //
        .isNotEqualTo(HIDE);
    return myself;
    }

    /**
    * 宽
    *
    * @param width 宽
    * @return S
    */
    public S hasWidth(int width) {
    isNotNull();
    int actualWidth = actual.getWidth();
    assertThat(actualWidth) //
        .overridingErrorMessage("Expected width <%s> but was <%s>", width, actualWidth) //
        .isEqualTo(width);
    return myself;
    }

    /**
    * X轴值
    *
    * @param floatX X轴值
    * @return S
    */
    public S hasX(float floatX) {
    isNotNull();
    float actualX = actual.getContentPositionX();
    assertThat(actualX) //
        .overridingErrorMessage("Expected x <%s> but was <%s>", floatX, actualX) //
        .isEqualTo(floatX);
    return myself;
    }

    /**
    * y轴值
    *
    * @param floatY y轴值
    * @return S
    */
    public S hasY(float floatY) {
    isNotNull();
    float actualY = actual.getBottom();
    assertThat(actualY) //
        .overridingErrorMessage("Expected y <%s> but was <%s>", floatY, actualY) //
        .isEqualTo(floatY);
    return myself;
    }

    /**
    * 有焦点
    *
    * @return S
    */
    public S hasFocus() {
    isNotNull();
    assertThat(actual.hasFocus()) //
        .overridingErrorMessage("Expected to have focus but was not focused") //
        .isTrue();
    return myself;
    }

    /**
    * 没有焦点
    *
    * @return S
    */
    public S hasNoFocus() {
    isNotNull();
    assertThat(actual.hasFocus()) //
        .overridingErrorMessage("Expected to not have focus but was focused") //
        .isFalse();
    return myself;
    }

    /**
    * 可聚焦
    *
    * @return S
    */
    public S hasFocusable() {
    isNotNull();
    assertThat(actual.hasFocus()) //
        .overridingErrorMessage("Expected to have focusable but was not") //
        .isTrue();
    return myself;
    }

    /**
    * 可点击
    *
    * @return S
    */
    public S isClickable() {
    isNotNull();
    assertThat(actual.isClickable()) //
        .overridingErrorMessage("Expected to be clickable but was not") //
        .isTrue();
    return myself;
    }

    /**
    * 不可点击
    *
    * @return S
    */
    public S isNotClickable() {
    isNotNull();
    assertThat(actual.isClickable()) //
        .overridingErrorMessage("Expected to not be clickable but was") //
        .isFalse();
    return myself;
    }

    /**
    * 是否启用
    *
    * @return S
    */
    public S isEnabled() {
    isNotNull();
    assertThat(actual.isEnabled()) //
        .overridingErrorMessage("Expected to be enabled but was disabled") //
        .isTrue();
    return myself;
    }

    /**
    * 是否禁用
    *
    * @return S
    */
    public S isDisabled() {
    isNotNull();
    assertThat(actual.isEnabled()) //
        .overridingErrorMessage("Expected to be disabled but was enabled") //
        .isFalse();
    return myself;
    }

    /**
    * 是否聚焦
    *
    * @return S
    */
    public S isFocusable() {
    isNotNull();
    assertThat(actual.isFocusable()) //
        .overridingErrorMessage("Expected to be focusable but was not") //
        .isTrue();
    return myself;
    }

    /**
    * 不可聚焦
    *
    * @return S
    */
    public S isNotFocusable() {
    isNotNull();
    assertThat(actual.isFocusable()) //
        .overridingErrorMessage("Expected to not be focusable but was") //
        .isFalse();
    return myself;
    }

    /**
    * 聚焦触控模式
    *
    * @return S
    */
    public S isFocusableInTouchMode() {
    isNotNull();
    assertThat(actual.isTouchFocusable()) //
        .overridingErrorMessage("Expected to be focusable in touch mode but was not") //
        .isTrue();
    return myself;
    }

    /**
    * 不可聚焦触控模式
    *
    * @return S
    */
    public S isNotFocusableInTouchMode() {
    isNotNull();
    assertThat(actual.isTouchFocusable()) //
        .overridingErrorMessage("Expected to not be focusable in touch mode but was") //
        .isFalse();
    return myself;
    }

    /**
    * 聚焦
    *
    * @return S
    */
    public S isFocused() {
    isNotNull();
    assertThat(actual.isFocused()) //
        .overridingErrorMessage("Expected to be focused but was not") //
        .isTrue();
    return myself;
    }

    /**
    * 不聚焦
    *
    * @return S
    */
    public S isNotFocused() {
    isNotNull();
    assertThat(actual.isFocused()) //
        .overridingErrorMessage("Expected to not be focused but was") //
        .isFalse();
    return myself;
    }

    /**
    * 已启用水平滚动条
    *
    * @return S
    */
    public S hasHorizontalScrollbarEnabled() {
    isNotNull();
    assertThat(actual.isScrollBarOn(AXIS_X)) //
        .overridingErrorMessage(
            "Expected to have horizontal scroll bar enabled but was disabled") //
        .isTrue();
    return myself;
    }

    /**
    * 已禁用水平滚动条
    *
    * @return S
    */
    public S hasHorizontalScrollbarDisabled() {
    isNotNull();
    assertThat(actual.isScrollBarOn(AXIS_X)) //
        .overridingErrorMessage(
            "Expected to have horizontal scroll bar disabled but was enabled") //
        .isFalse();
    return myself;
    }

    /**
    * 是否长点击
    *
    * @return S
    */
    public S isLongClickable() {
    isNotNull();
    assertThat(actual.isLongClickOn()) //
        .overridingErrorMessage("Expected to be long-clickable but was not") //
        .isTrue();
    return myself;
    }

    /**
    * 是否长点击
    *
    * @return S
    */
    public S isNotLongClickable() {
    isNotNull();
    assertThat(actual.isLongClickOn()) //
        .overridingErrorMessage("Expected to not be long-clickable but was") //
        .isFalse();
    return myself;
    }

    /**
    * 是否按压
    *
    * @return S
    */
    public S isPressed() {
    isNotNull();
    assertThat(actual.isPressed()) //
        .overridingErrorMessage("Expected to be pressed but was not") //
        .isTrue();
    return myself;
    }

    /**
    * 是否按压
    *
    * @return S
    */
    public S isNotPressed() {
    isNotNull();
    assertThat(actual.isPressed()) //
        .overridingErrorMessage("Expected to not be pressed but was") //
        .isFalse();
    return myself;
    }

    /**
    * 是否启用滚动条衰落
    *
    * @return S
    */
    public S hasScrollbarFadingEnabled() {
    isNotNull();
    assertThat(actual.isScrollbarFadingOn()) //
        .overridingErrorMessage("Expected to have scroll bar fading enabled but was disabled") //
        .isTrue();
    return myself;
    }

    /**
    * 是否关闭滚动条衰落
    *
    * @return S
    */
    public S hasScrollbarFadingDisabled() {
    isNotNull();
    assertThat(actual.isScrollbarFadingOn()) //
        .overridingErrorMessage("Expected to have scroll bar fading disabled but was enabled") //
        .isFalse();
    return myself;
    }

    /**
    * 是否选中
    *
    * @return S
    */
    public S isSelected() {
    isNotNull();
    assertThat(actual.isSelected()) //
        .overridingErrorMessage("Expected to be selected but was not") //
        .isTrue();
    return myself;
    }

    /**
    * 是否没选中
    *
    * @return S
    */
    public S isNotSelected() {
    isNotNull();
    assertThat(actual.isSelected()) //
        .overridingErrorMessage("Expected to not be selected but was") //
        .isFalse();
    return myself;
    }

    /**
    * 是否显示
    *
    * @return S
    */
    public S isShown() {
    isNotNull();
    assertThat(actual.isComponentDisplayed()) //
        .overridingErrorMessage("Expected to be shown but was not") //
        .isTrue();
    return myself;
    }

    /**
    * 是否显示
    *
    * @return S
    */
    public S isNotShown() {
    isNotNull();
    assertThat(actual.isComponentDisplayed()) //
        .overridingErrorMessage("Expected to not be shown but was") //
        .isFalse();
    return myself;
    }

    /**
    * 已启用垂直滚动条
    *
    * @return S
    */
    public S hasVerticalScrollBarEnabled() {
    isNotNull();
    assertThat(actual.isScrollBarOn(AXIS_Y)) //
        .overridingErrorMessage("Expected to have vertical scroll bar enabled but was disabled") //
        .isTrue();
    return myself;
    }

    /**
    * 已禁用垂直滚动条
    *
    * @return S
    */
    public S hasVerticalScrollBarDisabled() {
    isNotNull();
    assertThat(actual.isScrollBarOn(AXIS_Y)) //
        .overridingErrorMessage("Expected to have vertical scroll bar disabled but was enabled") //
        .isFalse();
    return myself;
    }

    /**
    * 是否附加到窗口
    *
    * @return S
    */
    public S isAttachedToWindow() {
    isNotNull();
    assertThat(actual.isBoundToWindow()) //
        .overridingErrorMessage("Expected to be attached to window but was not.") //
        .isTrue();
    return myself;
    }

    /**
    * 是否未附着到窗口
    *
    * @return S
    */
    public S isNotAttachedToWindow() {
    isNotNull();
    assertThat(actual.isBoundToWindow()) //
        .overridingErrorMessage("Expected to be not attached to window but was.") //
        .isFalse();
    return myself;
    }

    /**
    * 是否可见
    *
    * @param visibility 可见
    * @return S
    */
    public static String visibilityToString(int visibility) {
    return buildNamedValueString(visibility)
        .value(VISIBLE, "visible")
        .value(INVISIBLE, "invisible")
        .value(HIDE, "hide")
        .get();
    }

    /**
    * 布局方向
    *
    * @param direction 布局方向
    * @return S
    */
    public static String layoutDirectionToString(LayoutDirection direction) {
    return buildNamedValueString(direction.ordinal())
        .value(LayoutDirection.RTL.ordinal(), "right_to_left")
        .value(LayoutDirection.LTR.ordinal(), "left_to_right")
        .value(LayoutDirection.INHERIT.ordinal(), "inherit")
        .value(LayoutDirection.LOCALE.ordinal(), "locale")
        .get();
    }
}
